
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.BizObj.basic;
using Swaf.Container;
using Swaf.Xml;

using Syrinx;

namespace MediaCache
{
	/// <summary>
	/// Designed to use DataAccess (mostly database types) to store the images both as the
	/// "origionals" location and the "cached scaled" location.  The actual images are designed
	/// to be stored within rows of a table within a database.
	/// </summary>
	public class DataAccessImageCache : BaseImageCache
	{
        /// <summary>
        /// 
        /// </summary>
        /// <param name="req"></param>
        /// <param name="catalogName"></param>
		public DataAccessImageCache(LineInfoXmlElement req, Swaf.Container.XmlCatalogContainerNode.NameInfo catalogName)
			:base(req, catalogName)
		{
			//TODO: Verify the propar DARs are defined.
		}
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="listOf"></param>
        /// <param name="fileFilters"></param>
        /// <returns></returns>
		public override IBizObjList getImages(ImageListType listOf, string fileFilters)
		{
            return getImages(null, listOf, fileFilters);
		}
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseLocation"></param>
        /// <returns></returns>
        public override IBizObjList getLocations(string baseLocation)
        {
            return null;
        }
        
		protected override string getOrigionalImageFileNameExt(string imageFileName)
		{
			int pos = imageFileName.LastIndexOfAny(s_divider);
			FlexiMap m = new FlexiMap();
			m["location"] = "";

			if(pos != -1)
			{
				m["location"] = imageFileName.Substring(0, pos);
				imageFileName = imageFileName.Substring(pos +1);
			}

			if((pos = imageFileName.LastIndexOf('.')) != -1)
				imageFileName = imageFileName.Substring(0,pos);
			m["name"] = imageFileName + "%";
			string extName = "";
			string darName = "Data." + (string)m_cacheOptions.get("MediaCache.getImagesMatch");
			IBizObjList lst = (IBizObjList)Application.currentApp.appData.get(darName, m);
			foreach(IBizObj imgObj in lst)
			{
				if(imgObj.get("adjustName") == null)
				{
					extName = (string)imgObj.get("name");
					if((pos = extName.LastIndexOf('.')) != -1)
						extName = extName.Substring(pos+1);
					return extName;
				}
			}

			return null;
		}
        
		protected override IBizObj retrieveImage(string name, IBizObj scaleOptions, IBizObj imgAdjInfo)
		{
			FlexiMap m = new FlexiMap();
			m["name"] = Path.GetFileName(name);
			m["location"] = Path.GetDirectoryName(name);
			if(scaleOptions != null)
				m["adjustName"] = scaleOptions.get("name");
			else
				m["adjustName"] = null;
			string darName = "Data." + (string)m_cacheOptions.get("getImage");
			IBizObjList lst = (IBizObjList)Application.currentApp.appData.get(darName, m);
			if(lst.numElements != 0)
				return lst[0];
			return null;
		}

        protected override bool isScaledImageOutdated(string imageFileName, IBizObj scaleOptions, IBizObj imgAdjInfo)
		{
			int pos = imageFileName.LastIndexOfAny(s_divider);
			FlexiMap m = new FlexiMap();
			m["location"] = "";
			m["name"] = imageFileName;

			if(pos != -1)
			{
				m["location"] = imageFileName.Substring(0, pos);
				m["name"] = imageFileName.Substring(pos +1);
			}

			DateTime origImgDate = DateTime.MinValue;
			DateTime scaledImgDate = DateTime.MinValue;

			string darName = "Data." + (string)m_cacheOptions.get("getImagesMatch");
			IBizObjList lst = (IBizObjList)Application.currentApp.appData.get(darName, m);
			string scaleName = (string)scaleOptions.get("name");
			foreach(IBizObj img in lst)
			{
				string adjustName = (string)img.get("adjustName");
				if(adjustName == null)
					origImgDate = (DateTime)img.get("creationDate");
				else if(adjustName == scaleName)
					scaledImgDate = (DateTime)img.get("creationDate");
			}
			if(scaledImgDate > origImgDate)
				return false;

			return true;
		}
        
        protected override MediaStream retrieveImageStream(string name, IBizObj scaleOptions, IBizObj imgAdjInfo)
		{
			FlexiMap m = new FlexiMap();
			m["name"] = Path.GetFileName(name);
			if(scaleOptions != null)
				m["adjustName"] = scaleOptions.get("name");
			else
				m["adjustName"] = DBNull.Value;
			m["location"] = Path.GetDirectoryName(name);

			string darName = "Data." + (string)m_cacheOptions.get("getImage");
			IBizObjList lst = (IBizObjList)Application.currentApp.appData.get(darName, m);
			if(lst.numElements != 0)
			{
				return new MediaStream((string)lst[0].get("type"), ((Binary)lst[0].get("data")).Bytes, (string)lst[0].get("name"));
			}
			return null;
		}
        
        protected override void saveImage(System.Drawing.Bitmap image, string name, Swaf.BizObj.IBizObj scaleOptions, IBizObj imgAdjInfo, System.Drawing.Imaging.EncoderParameters eps)
		{
			IApplication app = Application.currentApp;
			MemoryStream m = new MemoryStream();
			image.Save(m, getDesiredEncoder(Path.GetExtension(name).Substring(1)), eps);

			IBizObj imgObj = app.bizObjMgr.create("ImageCacheImage");
			imgObj.put("name", Path.GetFileName(name));
			if(scaleOptions != null)
			{
				imgObj.put("adjustName", scaleOptions.get("name"));
				imgObj.put("type", MediaStream.calcMimeType((string)scaleOptions.get("imageType")));
			}
			imgObj.put("location", Path.GetDirectoryName(name));
			imgObj.put("data", new Binary(m.ToArray()));
			imgObj.put("creationDate", DateTime.Now);
			imgObj.put("width", image.Width);
			imgObj.put("height", image.Height);

			//Check db to see if the image already is in the db.
			string darName = "Data." + (string)m_cacheOptions.get("getImageId");
			IBizObjList matches = (IBizObjList)app.appData.get(darName, imgObj);
			if(matches.numElements == 0)
			{
				//If image with given name, location and adjustName are not in the db
				//Then we need to add the image.
				imgObj.put("id", new Swaf.BGuid.Guid());
				darName = "Data." + (string)m_cacheOptions.get("addImage");
			}
			else
			{
				//If the given image info are in the db then we need to update the
				//record with the new info.
				imgObj.put("id", matches[0].get("id"));
				darName = "Data." + (string)m_cacheOptions.get("updateImage");
			}
			app.appData.get(darName, imgObj);

		}
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="listOf"></param>
        /// <param name="fileFilters"></param>
        /// <returns></returns>
        public override IBizObjList getImages(string dirPath, ImageListType listOf, string fileFilters)
        {
            string name = "Data." + (string)m_cacheOptions.get("getList");
            IBizObjList lst = (IBizObjList)Application.currentApp.appData.get(name, new FlexiMap());
            return lst;
        }
    }
}
